﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NHibernate;
using NHibernate.Criterion;

using BOSS.Framework.Search;
using BOSS.Framework.Search.Context;
using BOSS.Domain.Products;
using BOSS.Dao.Products;

namespace BOSS.Dao.NHibernate.Products
{
    public class ProductDao : EntityDao<Product, int>, IProductDao
    {
        #region ISearchSupport<Product> 成员

        public IList<Product> SelectBySearch(ISearchContext context, out int totalCount)
        {
            int count = 0;

            string name = context.GetFilterTermValueAsString("Name");
            string model = context.GetFilterTermValueAsString("Model");
            bool? marketable = context.GetFilterTermValueAsBoolean("Marketable");

            IList<Product> products = this.HibernateTemplate.ExecuteFind<Product>(delegate(ISession session)
            {
                ICriteria criteria = session.CreateCriteria(typeof(Product), "p");

                if (!string.IsNullOrEmpty(name))
                {
                    criteria.Add(Expression.Like("p.Name", name, MatchMode.Anywhere));
                }

                if (!string.IsNullOrEmpty(model))
                {
                    criteria.Add(Expression.Like("p.Model", model, MatchMode.Anywhere));
                }

                if (marketable != null)
                {
                    criteria.Add(Expression.Eq("p.Marketable", marketable));
                }

                count = criteria.SetProjection(Projections.Count("Id").SetDistinct()).UniqueResult<int>();
                if (count == 0)
                {
                    return new List<Product>();
                }

                criteria.SetProjection(new IProjection[] { null });
                criteria.SetResultTransformer(CriteriaSpecification.DistinctRootEntity);

                if (context.SortCount > 0)
                {
                    foreach (var item in context.Sorts)
                    {
                        Order order = new Order(criteria.Alias + "." + item.FieldName, !item.Descend);
                        criteria.AddOrder(order);
                    }
                }

                return criteria.SetFirstResult(context.PageSize * (context.PageIndex - 1))
                            .SetMaxResults(context.PageSize)
                            .List<Product>();
            });

            totalCount = count;
            return products;
        }

        #endregion
    }
}
